<?php
//=======================================
//###################################
// Kayako Web Solutions
//
// Source Copyright 2001-2004 Kayako Infotech Ltd.
// Unauthorized reproduction is not allowed
// License Number: $%LICENSE%$
// $Author: vshoor $ ($Date: 2006/04/11 20:58:14 $)
// $RCSfile: functions_syncml.php,v $ : $Revision: 1.4 $ 
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
//###################################
//=======================================


/**
* Core class that handles all basic SyncML Functions
*/
class SyncML
{
	var $requestHeaders = array();
	var $requestBody = array();
	var $requestCred = array();
	var $request = array();
	var $deviceInfo = array();

	var $responseHeader = "";
	var $responseBody = "";
	var $responseCmdID = 1;

	/**
	* Parses the Raw SyncML Request and converts it into an array
	*/
	function parseRawRequest($syncmlrequest)
	{
		global $xml;
	
		$this->request = $xml->xml2tree($syncmlrequest);

		if (is_array($this->request))
		{
			return true;
		} else {
			return false;
		}
	}

	/**
	* Parses Request Headers and gets all basic protocol information
	*/
	function parseRequestHeader()
	{
		$synchdr = &$this->request["SyncML"][0]["children"]["SyncHdr"][0]["children"];
		
		$this->requestHeaders["version"] = $synchdr["VerDTD"][0]["values"][0];
		$this->requestHeaders["protocolversion"] = $synchdr["VerProto"][0]["values"][0];
		$this->requestHeaders["sourcesessionid"] = $synchdr["SessionID"][0]["values"][0];
		$this->requestHeaders["msgid"] = $synchdr["MsgID"][0]["values"][0];

		$this->requestHeaders["target_LocURI"] = $synchdr["Target"][0]["children"]["LocURI"][0]["values"][0];
		$this->requestHeaders["source_LocURI"] = $synchdr["Source"][0]["children"]["LocURI"][0]["values"][0];

		$this->requestHeaders["meta_MaxMsgSize"] = $synchdr["Meta"][0]["children"]["MaxMsgSize"][0]["values"][0];

		// Get credentials if set
		if (isset($synchdr["Cred"]))
		{
			// Type of auth, plain old base64 or md5?
			$credformat = $synchdr["Cred"][0]["children"]["Meta"][0]["children"]["Format"][0]["values"][0];
			$credtype = $synchdr["Cred"][0]["children"]["Meta"][0]["children"]["Type"][0]["values"][0];
			$creddata = $synchdr["Cred"][0]["children"]["Data"][0]["values"][0];

			if ($credtype == "syncml:auth-basic")
			{
				$decodeddata = base64_decode($creddata);
				$sep = strcspn($decodeddata, ":");
				$len = strlen($decodeddata);
			
				$this->requestCred["username"] = substr($decodeddata, 0, $sep);
				$this->requestCred["password"] = substr($decodeddata, $sep+1, ($len - $sep - 1));

				if (trim($this->requestCred["username"]) == "")
				{
					$this->requestCred = false;
				}
			} else if ($credtype == "syncml:auth-md5") {
				// !! CODE LATER ON !!
			}
			
		}
	}

	/**
	* Makes up a response header of already parsed strings, This assumes you have already build up the parent tags
	*/
	function addResponseHeader()
	{
		global $xml;

		$xml->indent++;

		$response .= $xml->returnTag("VerDTD", $this->requestHeaders["version"]);
		$response .= $xml->returnTag("VerProto", $this->requestHeaders["protocolversion"]);
		$response .= $xml->returnTag("SessionID", $this->requestHeaders["sourcesessionid"]);
		$response .= $xml->returnTag("MsgID", $this->requestHeaders["msgid"]);
			
		$response .= $xml->returnParentTag("Target");
			$response .= $xml->returnTag("LocURI", $this->requestHeaders["source_LocURI"]);
		$response .= $xml->returnEndTag("Target");

		$response .= $xml->returnParentTag("Source");
			$response .= $xml->returnTag("LocURI", $this->requestHeaders["target_LocURI"]);
		$response .= $xml->returnEndTag("Source");
			
		$xml->indent--;

		$this->responseHeader .= $response;

		return true;
	}

	/**
	* Adds a Status command
	*/
	function addStatusCommand($cmdref, $datacontents)
	{
		global $xml;
		
		$xml->indent++;

		$body .= $xml->returnParentTag("Status");
			
			$body .= $xml->returnTag("CmdID", $this->responseCmdID);
			$body .= $xml->returnTag("MsgRef", $this->requestHeaders["msgid"]);
			$body .= $xml->returnTag("CmdRef", $cmdref);
			$body .= $xml->returnTag("Cmd", "SyncHdr");
			$body .= $xml->returnTag("TargetRef", $this->requestHeaders["target_LocURI"]);
			$body .= $xml->returnTag("SourceRef", $this->requestHeaders["source_LocURI"]);
			$body .= $xml->returnTag("Data", $datacontents);

		$body .= $xml->returnEndTag("Status");

		$xml->indent--;
		$this->responseCmdID++;

		$this->responseBody .= $body;
	}

	/**
	* Processes the commands like Put, Get, Alert, Sync etc
	*/
	function processCommands()
	{
		global $xml, $_SWIFT, $debug;

		$syncbody = $this->request["SyncML"][0]["children"]["SyncBody"][0]["children"];
		$debug .= "In Process Commands\n";

		foreach ($syncbody as $key=>$val)
		{
			$finalval = &$val[0]["children"];
			if ($key == "Put")
			{
				$debug .= "Command Type is: PUT\n";
				$this->processPutCommand($finalval);
			} else if ($key == "Get") {
				$debug .= "Command Type is: GET\n";
				$this->processGetCommand($finalval);
			} else if ($key == "Alert") {
				$debug .= "Command Type is: ALERT\n";
				
			} else if ($key == "Sync") {
				$debug .= "Command Type is: SYNC\n";
				
			} else if ($key == "Final") {
				$debug .= "Command Type is: FINAL\n";
				
			} else if ($key == "Status") {
				$debug .= "Command Type is: STATUS\n";
				
			} else {
				$debug .= "Unrecognized Command Type: ". $key ."\n";
				// Unrecognized
			}								
		}
	}

	/**
	* Processes the Put Command
	*/
	function processPutCommand($command)
	{
		global $xml, $_SWIFT, $debug;

		$cmdid = $command["CmdID"][0]["values"][0];
		$metatype = $command["Meta"][0]["children"]["Type"][0]["values"][0];

		$this->addStatusCommand($cmdid, "200");

		// Is the SyncML Client sending the Device Info? Great! Fill up the deviceInfo Data. We dont use it right now but I am just adding it just in case.. dont want to go through the massive SyncML Spec later on to add one small feature - Varun
		if ($metatype == "application/vnd.syncml-devinf+xml")
		{
			$data = $command["Item"][0]["children"]["Data"][0]["children"]["DevInf"][0]["children"];
			if (is_array($data))
			{
				$this->deviceInfo["Manufacturer"] = $data["Man"][0]["values"][0];
				$this->deviceInfo["Model"] = $data["Mod"][0]["values"][0];
				$this->deviceInfo["OEM"] = $data["OEM"][0]["values"][0];
				$this->deviceInfo["FirmwareVersion"] = $data["FwV"][0]["values"][0];
				$this->deviceInfo["SoftwareVersion"] = $data["SwV"][0]["values"][0];
				$this->deviceInfo["HardwareVersion"] = $data["HwV"][0]["values"][0];
				$this->deviceInfo["DeviceType"] = $data["DevTyp"][0]["values"][0];
				$this->deviceInfo["DeviceID"] = $data["DevID"][0]["values"][0];
			}
		}
	}

	/**
	* Processes the Get Command
	*/
	function processGetCommand($command)
	{
		global $xml, $_SWIFT, $debug;

		$cmdid = $command["CmdID"][0]["values"][0];
		$metatype = $command["Meta"][0]["children"]["Type"][0]["values"][0];
		$locuri = $command["Item"][0]["children"]["Target"][0]["children"]["LocURI"][0]["values"][0];
		
		$debug .= "Inside Get Command ($cmdid)\n";

		// Send the SyncML Server Information
		if ($metatype == "application/vnd.syncml-devinf+xml")
		{
			$this->addStatusCommand($cmdid, "200");
			$xml->indent++;

			$body .= $xml->returnParentTag("Results");
				$body .= $xml->returnTag("CmdID", $this->responseCmdID);
				$body .= $xml->returnTag("MsgRef", $this->requestHeaders["msgid"]);
				$body .= $xml->returnTag("CmdRef", $cmdid);
				
					$body .= $xml->returnParentTag("Meta");
						$body .= $xml->returnTag("Type", "application/vnd.syncml-devinf+xml", array("xmlns" => "syncml:metinf"));
					$body .= $xml->returnEndTag("Meta");

				$body .= $xml->returnParentTag("Item");
					
					$body .= $xml->returnParentTag("Source");
						$body .= $xml->returnTag("LocURI", $locuri);
					$body .= $xml->returnEndTag("Source");
				
					$body .= $xml->returnParentTag("Data");
						$body .= $xml->returnParentTag("DevInf", array("xmlns" => "syncml:devinf"));
							$body .= $xml->returnTag("VerDTD", $this->requestHeaders["version"]);
							$body .= $xml->returnTag("Man", "HC Jsc.");
							$body .= $xml->returnTag("Mod", SWIFTPRODUCT);
							$body .= $xml->returnTag("FwV", SWIFTVERSION);
							$body .= $xml->returnTag("DevTyp", "server");
							$body .= $xml->returnTag("DevID", md5(SWIFTPRODUCT.SWIFTVERSION));
						$body .= $xml->returnEndTag("DevInf");
					$body .= $xml->returnEndTag("Data");

				$body .= $xml->returnEndTag("Item");


			$body .= $xml->returnEndTag("Results");
			$xml->indent--;

			$this->responseCmdID++;
			$this->responseBody .= $body;
		} else {
			$this->addStatusCommand($cmdid, "404");			
		}
	}
}

?>